import { getBaseUrl } from "@/utils/env";

const HTTP_REQUEST_URL = getBaseUrl();

import { useTokenStore } from "@/store";
// 从pina中读取 token 用于封装上传图片请求头
const tokenStore = useTokenStore();
const token = tokenStore.token;
/**
 * 小程序头像获取上传
 * @param uploadUrl 上传接口地址
 * @param filePath 上传文件路径
 * @param successCallback success回调
 * @param errorCallback err回调
 */
export function uploadImgs(
	uploadUrl : string,
	filePath : string,
	successCallback : Function,
	errorCallback : Function
) {
	uni.uploadFile({
		url: HTTP_REQUEST_URL + uploadUrl,
		filePath: filePath,
		name: "file",
		header: {
			"api-token": token,
			"api-name": "wxapp",
			"Content-Type": "application/x-www-form-urlencoded",
		},
		success: (res) => {
			if (res.statusCode == 403) {
				Tips({
					title: res.data,
				});
			} else {
				let data = res.data ? JSON.parse(res.data) : {};
				if (data.code == 1) {
					successCallback && successCallback(data);
				} else {
					errorCallback && errorCallback(data);
					Tips({
						title: data.msg,
					});
				}
			}
		},
		fail: (err) => {
			Tips({
				title: `上传图片失败`,
			});
		},
		complete: () => {
			uni.hideLoading();
		},
	});
}

/**
 * 获取image图片地址，代替require
 *
 * @param {string} path
 */
export function getImageUrl(name : string) {
	return new URL(`../static/image/${name}.png`, import.meta.url).href;
}
/**
 * 跳转路径封装函数
 * @param url 跳转路径
 */
// 一级页面路径
const tabPage = [
	"/pages/tabbar/home",
	"/pages/tabbar/about",
	"/pages/tabbar/my",
];
export function JumpPath(url : string) {
	let arr = url.split("@APPID=");
	if (arr.length > 1) {
		//#ifdef MP
		uni.navigateToMiniProgram({
			appId: arr[arr.length - 1],
			path: arr[0],
			envVersion: "release",
			success: (res) => {
				console.log("打开成功", res);
			},
			fail: (err) => { },
		});
		//#endif
		//#ifndef MP
		Tips({
			title: "h5与app端不支持跳转外部小程序",
		});
		//#endif
	} else {
		if (url.indexOf("http") != -1) {
			uni.navigateTo({
				url: `/pages/annex/web_view/index?url=${url}`,
			});
		} else {
			if (tabPage.indexOf(url) == -1) {
				uni.navigateTo({
					url,
				});
			} else {
				uni.switchTab({
					url,
				});
			}
		}
	}
}

/**
 * @param opt  object | string
 * @param to_url object | string
 * 例:
 * this.Tips('/pages/test/test'); 跳转不提示
 * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转
 * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上
 * tab=1 一定时间后跳转至 tabbar上
 * tab=2 一定时间后跳转至非 tabbar上
 * tab=3 一定时间后返回上页面
 * tab=4 关闭所有页面，打开到应用内的某个页面
 * tab=5 关闭当前页面，跳转到应用内的某个页面
 */
interface TipsOptions {
	title ?: string;
	icon ?: string;
	endtime ?: number;
	success ?: () => void;
}
interface ToUrlConfig {
	url ?: string;
	type ?: string;
	tab ?: number;
}
export function Tips(
	opt : TipsOptions | string,
	to_url ?: ToUrlConfig | string | Function
) : void {
	if (typeof opt == "string") {
		to_url = opt;
		opt = {};
	}
	let title = opt.title || "",
		icon = opt.icon || "none",
		endtime = opt.endtime || 2000,
		success = opt.success;
	if (title)
		uni.showToast({
			title: title,
			icon: [
				"success",
				"loading",
				"none",
				"error",
				"fail",
				"exception",
			].includes(icon)
				? (icon as
					| "success"
					| "none"
					| "loading"
					| "error"
					| "fail"
					| "exception")
				: "none",
			duration: endtime,
			success,
		});
	if (to_url != undefined) {
		if (typeof to_url == "object") {
			let tab = to_url.tab || 1,
				url = to_url.url || "";
			switch (tab) {
				case 1:
					//一定时间后跳转至 table
					setTimeout(function () {
						uni.switchTab({
							url: url,
						});
					}, endtime);
					break;
				case 2:
					//跳转至非table页面
					setTimeout(function () {
						uni.navigateTo({
							url: url,
						});
					}, endtime);
					break;
				case 3:
					//返回上页面
					setTimeout(function () {
						// #ifndef H5
						uni.navigateBack({
							delta: parseInt(url),
						});
						// #endif
						// #ifdef H5
						history.back();
						// #endif
					}, endtime);
					break;
				case 4:
					//关闭所有页面，打开到应用内的某个页面
					setTimeout(function () {
						uni.reLaunch({
							url: url,
						});
					}, endtime);
					break;
				case 5:
					//关闭当前页面，跳转到应用内的某个页面
					setTimeout(function () {
						uni.redirectTo({
							url: url,
						});
					}, endtime);
					break;
			}
		} else if (typeof to_url == "function") {
			setTimeout(function () {
				to_url && to_url();
			}, endtime);
		} else {
			//没有提示时跳转不延迟
			setTimeout(
				function () {
					uni.navigateTo({
						url: to_url,
					});
				},
				title ? endtime : 0
			);
		}
	}
}

/*
 * 单图上传
 * @param object opt
 * @param callable successCallback 成功执行方法 data
 * @param callable errorCallback 失败执行方法
 */
interface UploadImageOptions {
	url ?: string;
	name ?: string;
	count ?: number;
	sizeType ?: string[];
	sourceType ?: string[];
	is_load ?: boolean;
	//限定 fileType 类型
	fileType ?: "image" | "video" | "audio";
}
export function uploadImageOne(
	opt : UploadImageOptions | string,
	successCallback : Function,
	errorCallback : Function
) {
	if (typeof opt === "string") {
		let url = opt;
		opt = {};
		opt.url = url;
	}
	let count = opt.count || 1,
		sizeType = opt.sizeType || ["compressed"],
		sourceType = opt.sourceType || ["album", "camera"],
		is_load = opt.is_load || true,
		uploadUrl = opt.url || "",
		inputName = opt.name || "file",
		fileType = opt.fileType || "image";
	uni.chooseImage({
		count: count, //最多可以选择的图片总数
		sizeType: sizeType, // 可以指定是原图还是压缩图，默认二者都有
		sourceType: sourceType, // 可以指定来源是相册还是相机，默认二者都有
		success: function (res) {
			//启动上传等待中...
			uni.showLoading({
				title: "图片上传中",
			});
			uni.uploadFile({
				url: HTTP_REQUEST_URL + uploadUrl,
				filePath: res.tempFilePaths[0],
				fileType: fileType,
				name: inputName,
				formData: {
					filename: inputName,
					server: 1,
				},
				header: {
					// #ifdef MP
					"Content-Type": "application/form-data",
					// #endif
					"api-token": token,
					"api-name": "wxapp",
				},
				success: function (res) {
					uni.hideLoading();
					if (res.statusCode == 403) {
						Tips({
							title: res.data,
						});
					} else {
						let data = res.data ? JSON.parse(res.data) : {};
						if (data.code == 1) {
							successCallback && successCallback(data);
						} else {
							errorCallback && errorCallback(data);
							Tips({
								title: data.msg,
							});
						}
					}
				},
				fail: function (res) {
					uni.hideLoading();
					Tips({
						title: "上传图片失败",
					});
				},
			});
		},
	});
}
/*
 * 多图上传
 * @param object opt
 * @param callable successCallback 成功执行方法 data
 * @param callable errorCallback 失败执行方法
 */
export function uploadImageTwo(
	opt : UploadImageOptions | string,
	successCallback : Function,
	errorCallback : Function
) {
	if (typeof opt === "string") {
		let url = opt;
		opt = {};
		opt.url = url;
	}
	let count = opt.count || 2,
		sizeType = opt.sizeType || ["compressed"],
		sourceType = opt.sourceType || ["album", "camera"];

	uni.chooseImage({
		count: count, //最多可以选择的图片总数
		sizeType: sizeType, // 可以指定是原图还是压缩图，默认二者都有
		sourceType: sourceType, // 可以指定来源是相册还是相机，默认二者都有
		success(res) {
			//启动上传等待中...
			uni.showLoading({
				title: "图片上传中",
			});
			// 明确 tempFilePaths 是字符串数组
			const filePaths : string[] = Array.isArray(res.tempFilePaths)
				? res.tempFilePaths
				: [res.tempFilePaths];
			uploadFileFun(opt, filePaths, successCallback, errorCallback);
		},
	});
}
interface UploadFileOptions {
	url ?: string;
	name ?: string;
	count ?: number;
	sizeType ?: string[];
	sourceType ?: string[];
	is_load ?: boolean;
	//限定 fileType 类型
	fileType ?: "image" | "video" | "audio";
	// 其他可能需要的字段...
}
function uploadFileFun(
	opt : UploadFileOptions,
	arr : string[],
	successCallback : Function,
	errorCallback : Function
) {
	let is_load = opt.is_load || true,
		uploadUrl = opt.url || "",
		inputName = opt.name || "file",
		fileType = opt.fileType || "image";
	arr.forEach((item) => {
		uni.uploadFile({
			url: HTTP_REQUEST_URL + uploadUrl,
			filePath: item,
			fileType: fileType,
			name: inputName,
			formData: {
				filename: inputName,
				server: 1,
			},
			header: {
				// #ifdef MP
				"Content-Type": "application/form-data",
				// #endif
				"api-token": token,
				"api-name": "wxapp",
			},
			success: function (res) {
				uni.hideLoading();
				if (res.statusCode == 403) {
					Tips({
						title: res.data,
					});
				} else {
					let data = res.data ? JSON.parse(res.data) : {};
					if (data.code == 1) {
						successCallback && successCallback(data);
					} else {
						errorCallback && errorCallback(data);
						Tips({
							title: data.msg,
						});
					}
				}
			},
			fail: function (res) {
				uni.hideLoading();
				Tips({
					title: "上传图片失败",
				});
			},
		});
	});
}
/**
 * 预览图片
 * @param array url 预览的图片数组
 * @param number index 当前预览的图片索引，默认为0
 */
export function previewImageFun(urls : string[], current = 0) {
	if (!urls.length) {
		Tips({
			title: "预览图片失败：缺少有效的图片地址",
		});
		return;
	}
	uni.previewImage({
		urls,
		current,
		fail(err) {
			Tips({
				title: "图片加载失败",
			});
		},
	});
}
/**
 * 检测富文本是否含有图片，并将图片宽高分别设置为100%，auto
 * @param string data 富文本
 * @return string
 */
export function setRichData(data : string) {
	return data.replace(/<img/g, "<img style='width:100%;height:auto;'");
}
/**
 * 打开地图
 *
 */
interface showMaoLocationOptions {
	lat : string;
	lng : string;
	name ?: string;
	address ?: string;
}
export function showMaoLocation(
	data : showMaoLocationOptions,
	successCallback : Function
) {
	let { lat, lng, name, address } = data;
	if (!lat || !lng)
		return Tips({
			title: `缺少经纬度信息无法查看地图`,
		});
	uni.openLocation({
		latitude: parseFloat(lat),
		longitude: parseFloat(lng),
		scale: 8,
		name: name || "",
		address: address || "",
		success: function (data) {
			successCallback && successCallback(data);
		},
	});
}
/**
 * 腾讯地图逆解析地址，传入经纬度，返回地址信息
 * @param {string} lat lng 经纬度
 * @return {object} 地址信息
 * @return {string} 腾讯地址key值
 */
export function getAdress(
	lat : string,
	lng : string,
	key = "HMQBZ-XC7KD-WZ64J-PFOQM-CFMT6-HUBOX"
) {
	return new Promise((resolve, reject) => {
		uni.request({
			url:
				`https://apis.map.qq.com/ws/geocoder/v1/?key=${key}&location=` +
				lat +
				"," +
				lng,
			success(res) {
				return resolve(res);
			},
			fail(err) {
				return reject(err);
			},
		});
	});
}
const $h = {
	//除法函数，用来得到精确的除法结果
	//说明：javascript的除法结果会有误差，在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
	//调用：$h.Div(arg1,arg2)
	//返回值：arg1除以arg2的精确结果
	Div: function (arg1 : any, arg2 : any) {
		arg1 = parseFloat(arg1);
		arg2 = parseFloat(arg2);
		var t1 = 0,
			t2 = 0,
			r1,
			r2;
		try {
			t1 = arg1.toString().split(".")[1].length;
		} catch (e) { }
		try {
			t2 = arg2.toString().split(".")[1].length;
		} catch (e) { }
		r1 = Number(arg1.toString().replace(".", ""));
		r2 = Number(arg2.toString().replace(".", ""));
		return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
	},
	//加法函数，用来得到精确的加法结果
	//说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
	//调用：$h.Add(arg1,arg2)
	//返回值：arg1加上arg2的精确结果
	Add: function (arg1 : any, arg2 : any) {
		arg2 = parseFloat(arg2);
		var r1, r2, m;
		try {
			r1 = arg1.toString().split(".")[1].length;
		} catch (e) {
			r1 = 0;
		}
		try {
			r2 = arg2.toString().split(".")[1].length;
		} catch (e) {
			r2 = 0;
		}
		m = Math.pow(100, Math.max(r1, r2));
		return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
	},
	//减法函数，用来得到精确的减法结果
	//说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
	//调用：$h.Sub(arg1,arg2)
	//返回值：arg1减去arg2的精确结果
	Sub: function (arg1 : any, arg2 : any) {
		arg1 = parseFloat(arg1);
		arg2 = parseFloat(arg2);
		var r1, r2, m, n;
		try {
			r1 = arg1.toString().split(".")[1].length;
		} catch (e) {
			r1 = 0;
		}
		try {
			r2 = arg2.toString().split(".")[1].length;
		} catch (e) {
			r2 = 0;
		}
		m = Math.pow(10, Math.max(r1, r2));
		//动态控制精度长度
		n = r1 >= r2 ? r1 : r2;
		return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
	},
	//乘法函数，用来得到精确的乘法结果
	//说明：javascript的乘法结果会有误差，在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
	//调用：$h.Mul(arg1,arg2)
	//返回值：arg1乘以arg2的精确结果
	Mul: function (arg1 : any, arg2 : any) {
		arg1 = parseFloat(arg1);
		arg2 = parseFloat(arg2);
		var m = 0,
			s1 = arg1.toString(),
			s2 = arg2.toString();
		try {
			m += s1.split(".")[1].length;
		} catch (e) { }
		try {
			m += s2.split(".")[1].length;
		} catch (e) { }
		return (
			(Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) /
			Math.pow(10, m)
		);
	},
};
export { $h };
// 获取地理位置;
const $L = {
	async getLocation() {
		let status : number;
		// #ifdef APP-PLUS
		status = await this.checkPermission();
		if (status !== 1) {
			return;
		}
		// #endif
		// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
		status = (await this.getSetting()) as number;

		if (status === 2) {
			this.openSetting();
			return;
		}
		// #endif
		// #ifdef H5
		return this.h5GetLocation();
		// #endif
		// #ifndef H5
		return this.doGetLocation();
		// #endif
	},
	h5GetLocation() : Promise<{ latitude : number; longitude : number }> {
		return new Promise((resolve, reject) => {
			if (!navigator.geolocation) {
				uni.showToast({ title: "当前环境不支持定位", icon: "none" });
				reject(new Error("浏览器不支持 geolocation"));
				return;
			}

			navigator.geolocation.getCurrentPosition(
				(position) => {
					const latitude = position.coords.latitude;
					const longitude = position.coords.longitude;
					console.log("当前位置：", position);

					resolve({ latitude, longitude });
				},
				(error) => {
					let errorMsg = "";
					switch (error.code) {
						case error.PERMISSION_DENIED:
							errorMsg = "用户拒绝定位权限";
							break;
						case error.POSITION_UNAVAILABLE:
							errorMsg = "位置信息不可用";
							break;
						case error.TIMEOUT:
							errorMsg = "定位超时";
							break;
						default:
							errorMsg = "定位失败，请重试";
					}
					uni.showToast({ title: errorMsg, icon: "none" });
					reject(new Error(errorMsg));
				},
				{
					enableHighAccuracy: false,
					timeout: 3000,
					maximumAge: 0,
				}
			);
		});
	},
	doGetLocation() {

		return new Promise((resolve, reject) => {
			uni.getLocation({
				isHighAccuracy: true, // 开启高精度定位
				success: (res) => {
					console.log(res, "获取经纬度成功");
					uni.removeStorageSync("CACHE_LONGITUDE");
					uni.removeStorageSync("CACHE_LATITUDE");
					uni.setStorageSync("CACHE_LONGITUDE", res.longitude);
					uni.setStorageSync("CACHE_LATITUDE", res.latitude);
					resolve({ longitude: res.longitude, latitude: res.latitude });
				},
				fail: (err) => {
					// #ifdef MP-BAIDU
					if (err.errCode === 202 || err.errCode === 10003) {
						// 202模拟器 10003真机 user deny
						this.openSetting();
					}
					// #endif
					// #ifndef MP-BAIDU
					if (err.errMsg.indexOf("auth deny") >= 0) {
						uni.showToast({
							title: `访问位置被拒绝`,
							icon: "error",
						});
					} else {
						uni.showToast({
							title: err.errMsg,
							icon: "error",
						});
					}
					reject(err.errMsg);
					console.log(err, "错误");

					// #endif
				},
			});
		});
	},
	getSetting: function () {
		return new Promise((resolve, reject) => {
			uni.getSetting({
				success: (res) => {
					if (res.authSetting["scope.userLocation"] === undefined) {
						resolve(0);
						return;
					}
					if (res.authSetting["scope.userLocation"]) {
						resolve(1);
					} else {
						resolve(2);
					}
				},
				fail: (err) => {
					console.log(err, "获取设置失败");
				},
			});
		});
	},
	openSetting: function () {
		uni.openSetting({
			success: (res) => {
				if (res.authSetting && res.authSetting["scope.userLocation"]) {
					this.doGetLocation();
				}
			},
			fail: (err) => { },
		});
	},
	async checkPermission() {
		let status = permision.isIOS
			? await permision.requestIOS("location")
			: await permision.requestAndroid(
				"android.permission.ACCESS_FINE_LOCATION"
			);

		if (status === null || status === 1) {
			status = 1;
		} else if (status === 2) {
			uni.showModal({
				content: `系统定位已关闭`,
				confirmText: `确定`,
				showCancel: false,
				success: function (res) { },
			});
		} else if (status.code) {
			uni.showModal({
				content: status.message,
			});
		} else {
			uni.showModal({
				content: `需要定位权限`,
				confirmText: `确定`,
				success: function (res) {
					if (res.confirm) {
						permision.gotoAppSetting();
					}
				},
			});
		}
		return status;
	},
};
export { $L };